
#include "datparser.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <stdarg.h>

#include <fcntl.h>
#include <unistd.h>

#include <sys/ioctl.h>
#include <sys/stat.h>

#include <net/if.h>

#define CONFIG_DEAMON			1
//#define CONFIG_SHELL			1
#define CONFIG_DEAULT_SSID		1

#define USB_VID					0x2A5FU
#define USB_PID					0x1000U
#define IFNAME					"ra0"

static int skfd = 0;
static int process_status = 0;

#ifdef CONFIG_DEAMON
#define printf(fmt, ...)
#define LOG_FILE				"/dev/console"

static int log_fd = -1;
static char sprint_buf[256] = {0};

static void log_init(void)
{
	log_fd = open("/dev/console", O_RDWR);
	if(0 > log_fd)
	{
		log_fd = -1;
	}
}

static void log_out(char *fmt, ...)
{
	int n;
	va_list args;

	if(0 < log_fd)
	{
		va_start(args, fmt);
		n = vsprintf(sprint_buf, fmt, args);
		va_end(args);
		write(log_fd, sprint_buf, n);
	}
}
#endif

static int check_usb_exist(unsigned short vid, unsigned short pid)
{
	FILE *fp = fopen("/proc/bus/usb/devices", "r");
	char buf[10240] = {0};
	char *pvid = NULL, *ppid = NULL;

	unsigned int vid_r = 0, pid_r = 0; 

	if(NULL != fp)
	{
		fread(buf, 1, sizeof(buf), fp);
		fclose(fp);

		pvid = buf;

		while(1)
		{
			pvid = strstr(pvid, "Vendor=");
			if(NULL != pvid)
			{
				ppid = strstr(pvid, "ProdID=");
				if(NULL != ppid)
				{
					pvid[5] = '0';
					pvid[6] = 'x';

					ppid[5] = '0';
					ppid[6] = 'x';

					pvid[11] = 0;
					ppid[11] = 0;

					vid_r = strtoul(&pvid[5], 0, 0) & 0xFFFF;
					pid_r = strtoul(&ppid[5], 0, 0) & 0xFFFF;

					printf("VID = 0x%04X, PID = 0x%04X, ", vid_r, pid_r);

					if(vid_r == vid && pid_r == pid)
					{
						printf("match!!!\n");
						return 0;
					}

					printf("not match!!!\n");

					pvid = &ppid[12];
				}
			}
			else
			{
				break;
			}
		}
	}

	return -1;
}

static int check_if_list(void)
{
	if(0 == access("/proc/net/dev", F_OK) && 0 == access("/proc/net/dev", R_OK))
	{
		return 0;
	}
	return -1;
}

static int check_if_registered(char *ifname)
{
	FILE *fp = NULL;

	char fullname[32] = {0};
	char buf[1024] = {0};

	if(NULL != ifname && 0 == check_if_list())
	{
		fp = fopen("/proc/net/dev", "r");
		if(NULL != fp)
		{
			fread(buf, 1, sizeof(buf), fp);
			fclose(fp);

			snprintf(fullname, sizeof(fullname), "%s:", ifname);
			fullname[sizeof(fullname) - 1] = 0;

			if(NULL != strstr(buf, fullname))
			{
				return 0;
			}
		}
	}
	return -1;
}

static int get_if_status(char *ifname, unsigned int *val)
{
	struct ifreq ifr;

	if(NULL != ifname && NULL != val && 0 <= skfd)
	{
		strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
		if(0 == ioctl(skfd, SIOCGIFFLAGS, &ifr))
		{
			*val = ifr.ifr_flags;
			return 0;
		}
	}
	return -1;
}

static int set_if_status(char *ifname, unsigned int *val)
{
	struct ifreq ifr;

	if(NULL != ifname && NULL != val && 0 <= skfd)
	{
		//sleep(5);
		strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
		ifr.ifr_flags = *val;
		if(0 == ioctl(skfd, SIOCSIFFLAGS, &ifr))
		{
			//sleep(5);
			return 0;
		}
	}
	return -1;
}

static int check_if_enable(char *ifname)
{
	unsigned int flag = 0;
	if(0 == get_if_status(ifname, &flag))
	{
		if(0 == (IFF_UP & flag) && 0 == (IFF_RUNNING & flag))
		{
			return 0;
		}
	}
	return -1;
}

static int restore_data_file(void)
{
	int ret = 0;
	char buf[1024] = {0};

	FILE *psrc = NULL;
	FILE *pdest = NULL;

	pdest = fopen("/etc/Wireless/RT2870AP/RT2870AP.dat", "w+");
	if(NULL != pdest)
	{
		psrc = fopen("/etc/Wireless/RT2870AP/RT2870AP.dat.bak", "r");
		if(NULL != psrc)
		{
			ret = 1024;
			while(1024 <= ret)
			{
				ret = fread(buf, 1, sizeof(buf), psrc);
				fwrite(buf, 1, ret, pdest);

				fflush(psrc);
				fflush(pdest);

				//sleep(1);
			}
			fclose(psrc);
			fclose(pdest);

			system("md5sum /etc/Wireless/RT2870AP/RT2870AP.dat");
			return 0;
		}
		fclose(pdest);
	}
	return -1;
}

static int set_if_enable(char *ifname)
{
	unsigned int flag = 0;

	printf("......................set interface enable......................................\n");
	if(0 == get_if_status(ifname, &flag))
	{
		if(0 == process_status)
		{
			restore_data_file();
			process_status++;
		}
		flag |= (IFF_UP | IFF_RUNNING);
		return set_if_status(ifname, &flag);
	}
	return -1;
}

static int set_if_disable(char *ifname)
{
	unsigned int flag = 0;

	printf("......................set interface disable......................................\n");
	if(0 == get_if_status(ifname, &flag))
	{
		flag &= ~(IFF_UP | IFF_RUNNING);
		return set_if_status(ifname, &flag);
	}
	return -1;
}

static int get_if_hard_address(char *ifname, char *mac)
{
	int i = 0;
	struct ifreq ifr;

	if(NULL != ifname && NULL != mac && 0 <= skfd)
	{
		strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
		if(0 == ioctl(skfd, SIOCGIFHWADDR, &ifr))
		{
			for(i = 0; 6 > i; i++)
			{
				mac[i] = ifr.ifr_hwaddr.sa_data[i];
			}
			return 0;
		}
	}
	return -1;
}

static int set_wifi_ssid(char *ssid)
{
#ifdef CONFIG_DEAULT_SSID
	struct dat_stu *list = NULL;

	if(NULL != ssid && 6 < strlen(ssid))
	{
		if(0 == dat_load("/etc/Wireless/RT2870AP/RT2870AP.dat", &list))
		{
			if(NULL != list)
			{
				if(0 == dat_set_lable(list, "SSID", ssid, strlen(ssid)) && 0 == dat_set_lable(list, "WPAPSK", "16D9B53D478C452D", 16))
				{
					//dat_dump(list);
					dat_save("/etc/Wireless/RT2870AP/RT2870AP.dat", list);
				}
				dat_free(&list);
				return 0;
			}
		}
	}
	return -1;
#else
	return 0;
#endif
}

int main(int argc, char **argv)
{
#ifdef CONFIG_DEAMON
	int i = 0;
	int base_fd[3] = {0, 0, 0};

	pid_t pid = 0;
#endif
	char macaddr[6] = {0};
	char ssid[32] = {0};

#ifdef CONFIG_DEAMON
	pid = fork();

	if(0 == pid)
	{
		setsid();
		pid = fork();
		if(0 == pid)
		{
			setsid();
			chdir("/");
			umask(0);

			for(i = 0; 1024 > i; i++)
			{
				close(i);
			}

			base_fd[0] = open("/dev/null", O_RDWR);
			base_fd[1] = dup(0);
			base_fd[2] = dup(0);
			
			if(0 == base_fd[0] || 1 == base_fd[1] || 2 == base_fd[2])
			{
				log_init();
#endif
				skfd = socket(AF_INET, SOCK_DGRAM, 0);

				while(1)
				{
					if(0 == check_usb_exist(USB_VID, USB_PID))
					{
						if(0 == check_if_registered(IFNAME))
						{
							if(0 == check_if_enable(IFNAME))
							{
#ifdef CONFIG_SHELL
								sleep(30);
								system("ifconfig ra0 172.16.232.250 netmask 255.255.255.0 up");
								sleep(30);
								system("killall udhcpd");
								system("killall httpd");
								system("udhcpd -S -I 172.16.232.250 /etc/udhcpd.conf");
								system("httpd -h /www -c /etc/httpd.conf");
#else
#ifdef CONFIG_DEAMON
								log_out("\n\n\n!!!!!!!!!! USB WiFi Card is being initialized, please don't pull it down. !!!!!!!!!!\n\n\n");
								log_out("10%\n");
#endif
								process_status = 0;
								if(0 == set_if_enable(IFNAME))
								{
#ifdef CONFIG_DEAMON
									log_out("25%\n");
#endif
									
									if(0 == set_if_disable(IFNAME))
									{
#ifdef CONFIG_DEAMON
										log_out("50%\n");
#endif
										memset(macaddr, 0, sizeof(macaddr));
										if(0 == get_if_hard_address(IFNAME, macaddr) && (0 < macaddr[0] || 0 < macaddr[1] || 0 < macaddr[2] || 0 < macaddr[3] || 0 < macaddr[4] || 0 < macaddr[5]))
										{
#ifdef CONFIG_DEAMON
											log_out("75%\n");
#endif
											//printf("%02X%02X%02X%02X%02X%02X\n", macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
											memset(ssid, 0, sizeof(ssid));
											snprintf(ssid, sizeof(ssid), "AJB_%02X%02X%02X", macaddr[3], macaddr[4], macaddr[5]);
											if(0 == set_wifi_ssid(ssid))
											{
#ifdef CONFIG_DEAMON
												log_out("90%\n");
#endif
												if(0 == set_if_enable(IFNAME))
												{
#ifdef CONFIG_DEAMON
													log_out("\n\n\n!!! USB WiFi Card was initialized success !!!\n\n\n");
#endif
													//sleep(10);
													//set_if_disable(IFNAME);
												}
											}
										}
									}
								}
#endif
							}
						}
					}
#ifdef CONFIG_SHELL
					else
					{
						system("killall udhcpd");
						system("killall httpd");
					}
#endif
					sleep(1);
				}
#if CONFIG_DEAMON
			}
		}
	}
#endif
	return 0;
}
